/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/**
 * @Title: DocumentTranslator.java
 * @Package phoenics.apeak.crawl
 * @Description
 * @author phoenics@126com
 * @date 2016-1-30 16:01:31
 * @version V1.0
 */
package phoenics.apeak.crawl;

import org.eclipse.jetty.client.api.Response.Listener;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.client.util.BufferingResponseListener;
import org.springframework.context.ApplicationContext;

import com.lmax.disruptor.EventTranslator;

import phoenics.apeak.crawl.service.DocumentPublisher;

// TODO: Auto-generated Javadoc
/**
 * The Class DocumentTranslator.
 *
 * @Description The Class DocumentTranslator.
 */
public class DocumentTranslator  implements EventTranslator<Document> {
	
	/** The Constant mapper. */
	//private final static DozerBeanMapper mapper = new DozerBeanMapper();  
	
	/** The application context. */
	private ApplicationContext applicationContext;
	
	/** The url. */
	private String url;
	
	/** The params. */
	private String params;
	
	/** The extractor class. */
	private Class<? extends Extractor> extractorClass;
	
	/** The repeat. */
	private boolean repeat = false;
	
	/** The head. */
	private Map<HttpHead ,String> head=new HashMap<>();
	
	/** The listener. */
	private final Listener listener=new BufferingResponseListener(){
		@Override
		public void onComplete(Result result) {
			Extractor extractor = applicationContext.getBean(getExtractorClass());
			extractor.setParams(getParams());
			extractor.setUrl(getUrl());
			if (result.isFailed()) {
				DocumentPublisher documentPublisher = applicationContext.getBean(DocumentPublisher.class);
				documentPublisher.publish(getExtractorClass(), getUrl(), getParams(), true);
			} else {
				extractor.extract(this.getContent());
				DocumentHandle.errorMap.remove(getUrl());
			}
		}
		
	};
	
	/**
 * The Constructor.
 *
 * @param applicationContext
 *            the application context
 * @param extractorClass
 *            the extractor class
 * @param url
 *            the url
 * @param params
 *            the params
 * @param repeat
 *            the repeat
 * @Description Instantiates a new document translator.
 */
	public DocumentTranslator(ApplicationContext applicationContext, Class<? extends Extractor> extractorClass, String url, String params,boolean repeat) {
		this.setApplicationContext(applicationContext);
		this.setExtractorClass(extractorClass);
		this.setUrl(url);
		this.setParams(params);
		this.setRepeat(repeat);
		String agent = selectAgent();
		if (agent != null) {
			this.getHead().put(HttpHead.agent, agent);
		}
	}
	
	/**
 * The Constructor.
 *
 * @param applicationContext
 *            the application context
 * @Description Instantiates a new document translator.
 */
	public DocumentTranslator(ApplicationContext applicationContext) {
		this(applicationContext, null, null, null,false);
	}
	
	/**
 * The Constructor.
 *
 * @param applicationContext
 *            the application context
 * @param extractorClass
 *            the extractor class
 * @param url
 *            the url
 * @param repeat
 *            the repeat
 * @Description Instantiates a new document translator.
 */
	public DocumentTranslator(ApplicationContext applicationContext, Class<? extends Extractor> extractorClass, String url,boolean repeat) {
		this(applicationContext, extractorClass, url, null,repeat);
	}
	
	/**
 * The Constructor.
 *
 * @param applicationContext
 *            the application context
 * @param extractorClass
 *            the extractor class
 * @param url
 *            the url
 * @Description Instantiates a new document translator.
 */
	public DocumentTranslator(ApplicationContext applicationContext, Class<? extends Extractor> extractorClass, String url) {
		this(applicationContext, null, null, null,false);
	}
	
	/* (non-Javadoc)
	 * @see com.lmax.disruptor.EventTranslator#translateTo(java.lang.Object, long)
	 */
	@Override
	public void translateTo(Document event, long sequence) {
		//mapper.map(this, event);
		event.setApplicationContext(getApplicationContext());
		event.setExtractorClass(getExtractorClass());
		event.setListener(getListener());
		event.setParams(getParams());
		event.setRepeat(isRepeat());
		event.setUrl(getUrl());
		
	}
	
	/**
 * Gets the application context.
 *
 * @return the application context
 * @Description Gets the application context.
 */
	public ApplicationContext getApplicationContext() {
		return applicationContext;
	}
	
	/**
 * Sets the application context.
 *
 * @param applicationContext
 *            the new application context
 * @Description Sets the application context.
 */
	public void setApplicationContext(ApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
	}
	
	/**
 * Gets the url.
 *
 * @return the url
 * @Description Gets the url.
 */
	public String getUrl() {
		return url;
	}
	
	/**
 * Sets the url.
 *
 * @param url
 *            the new url
 * @Description Sets the url.
 */
	public void setUrl(String url) {
		this.url = url;
	}
	
	/**
 * Gets the params.
 *
 * @return the params
 * @Description Gets the params.
 */
	public String getParams() {
		return params;
	}
	
	/**
 * Sets the params.
 *
 * @param params
 *            the new params
 * @Description Sets the params.
 */
	public void setParams(String params) {
		this.params = params;
	}
	
	/**
 * Gets the extractor class.
 *
 * @return the extractor class
 */
	public Class<? extends Extractor> getExtractorClass() {
		return extractorClass;
	}
	
	/**
 * Sets the extractor class.
 *
 * @param extractorClass
 *            the new extractor class
 * @Description Sets the extractor class.
 */
	public void setExtractorClass(Class<? extends Extractor> extractorClass) {
		this.extractorClass = extractorClass;
	}
	
	/**
 * Checks if is repeat.
 *
 * @return true, if is repeat
 * @Description Checks if is repeat.
 */
	public boolean isRepeat() {
		return repeat;
	}
	
	/**
 * Sets the repeat.
 *
 * @param repeat
 *            the new repeat
 * @Description Sets the repeat.
 */
	public void setRepeat(boolean repeat) {
		this.repeat = repeat;
	}
	
	/**
 * Gets the listener.
 *
 * @return the listener
 * @Description Gets the listener.
 */
	public Listener getListener() {
		return listener;
	}
	
	/**
 * Select agent.
 *
 * @return the string
 * @Description Select agent.
 */
	private String selectAgent() {
		if (Document.headSelects.get(HttpHead.agent) == null) {
			return null;
		}
		List<String> agents = Document.headSelects.get(HttpHead.agent);
		int length = agents.size();
		if (length < 1) {
			return null;
		}
		int max = length - 1;
		Random random = new Random();
		int s = random.nextInt(max) % (max + 1);
		return agents.get(s);
	}
	
	/**
 * Gets the head.
 *
 * @return the head
 * @Description Gets the head.
 */
	public Map<HttpHead ,String> getHead() {
		return head;
	}

}
